package com.eastfair.builder.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.annotation.annotation.log.SysLog;
import com.eastfair.annotation.annotation.security.PreAuth;
import com.eastfair.boot.controller.SuperController;
import com.eastfair.boot.request.PageParams;
import com.eastfair.builder.dto.*;
import com.eastfair.builder.entity.Exhibitor;
import com.eastfair.builder.exceptioncode.BuilderExceptionCode;
import com.eastfair.builder.service.ExhibitorService;
import com.eastfair.builder.service.MeetActorService;
import com.eastfair.builder.vo.ActorInfo;
import com.eastfair.builder.vo.ExhibitorVO;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.echo.core.EchoService;
import com.eastfair.venueservice.dto.ServiceProviderSpaceQuery;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * <p>
 * 前端控制器
 * 展商
 * </p>
 *
 * @author dq
 * @date 2022-08-06
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/exhibitor")
@Api(value = "Exhibitor", tags = "展商")
@PreAuth(replace = "builder:exhibitor:")
public class ExhibitorController extends SuperController<ExhibitorService, Long, Exhibitor, ExhibitorPageQuery, ExhibitorSaveDTO, ExhibitorUpdateDTO> {

    @Resource
    private EchoService echoService;

    @Resource
    private ExhibitorService exhibitorService;

    @Resource
    private MeetActorService meetActorService;

    @Override
    public void handlerResult(IPage<Exhibitor> page) {
        // 想让返回值实现自动回显，请将此行代码打开
        // echoService.action(page);
    }

    /**
     * Excel导入后的操作
     *
     * @param list
     */
    @Override
    public R<Boolean> handlerImport(List<Map<String, String>> list) {
        List<Exhibitor> exhibitorList = list
                .stream()
                .map((map) -> Exhibitor.builder().build())
                .collect(Collectors.toList());
        return R.success(baseService.saveBatch(exhibitorList));
    }

    /**
     * 处理参数
     *
     * @param params 分页参数
     */
    @Override
    public void handlerQueryParams(PageParams<ExhibitorPageQuery> params) {
        ExhibitorPageQuery pageQuery = params.getModel();
        //分页处理
        if (ContextUtil.getProjectId() != null) {
            pageQuery.setProjectId(ContextUtil.getProjectId());
        }
    }

    /**
     * 分页查询展商VO列表.
     *
     * @param pageParams the page params
     * @return the r
     */
    @ApiOperation("分页查询展商VO列表")
    @PostMapping("/page/exhibitor")
    public R<Page<ExhibitorVO>> queryExhibitors(@RequestBody PageParams<ExhibitorDTO> pageParams) {
        log.info("queryExhibitors - 分页查询展商VO列表, pageParams={}", pageParams);
        return R.successDef(exhibitorService.listExhibitorVOs(pageParams));
    }

    /**
     * 查询展商VO列表.
     *
     * @param exhibitorDTO the exhibitor dto
     * @return the r
     */
    @ApiOperation("查询展商VO列表")
    @PostMapping("/query/exhibitor")
    public R<List<ExhibitorVO>> queryExhibitors(@RequestBody ExhibitorDTO exhibitorDTO) {
        log.info("queryExhibitors - 查询展商VO列表, pageParams={}", exhibitorDTO);
        return R.successDef(exhibitorService.listExhibitorVOs(exhibitorDTO));
    }

    /**
     * 通过展会，主场，展厅查询展位
     *
     * @param query the query
     * @return the r
     */
    @PostMapping("/query/providerSite")
    public R<Page<ExhibitorVO>> queryServiceProviderSite(@RequestBody PageParams<ExhibitorDTO> query) throws Exception {
        log.info("queryServiceProviderSite - 通过展会，主场，展厅查询展位, query:{}", query);
        Page<ExhibitorVO> r = exhibitorService.queryServiceProviderSite(query);
        return R.success(r);
    }

    /**
     * 通过展会查询展位
     *
     * @param query the query
     * @return the r
     */
    @PostMapping("/queryAllServiceProviderSite")
    public R<List<ExhibitorVO>> queryAllServiceProviderSite(@RequestBody ServiceProviderSpaceQuery query) {
        log.info("queryAllServiceProviderSite query:{}", JSONObject.toJSONString(query));
        List<ExhibitorVO> r = exhibitorService.queryAllServiceProviderSite(query);
        return R.success(r);
    }

    /**
     * 分页查询未报馆的展位列表.
     *
     * @param pageParams the page params
     * @return the r
     */
    @PostMapping("/query/not/reportSpace")
    public R<Page<ExhibitorVO>> queryNotReportSpaceExhibitors(@RequestBody PageParams<ExhibitorDTO> pageParams) {
        Page<ExhibitorVO> page = exhibitorService.listNotReportSpaceExhibitorVOs(pageParams);
        return R.successDef(page);
    }

    /**
     * 查询展商列表VO.
     *
     * @param exhibitorDTO the exhibitor dto
     * @return the exhibitor list
     */
    @Deprecated
    @GetMapping("/query/exhibitor")
    public R<List<ExhibitorVO>> getExhibitorList(ExhibitorDTO exhibitorDTO) {
        log.info("getExhibitorList - 查询展商列表VO, exhibitorDTO={}", exhibitorDTO);
        return R.successDef(exhibitorService.listExhibitorVOs(exhibitorDTO));
    }

    /**
     * 查询展商列表VO.
     *
     * @param exhibitorDTO the exhibitor dto
     * @return the exhibitor list
     */
    @GetMapping("/get/exhibitor/list")
    public R<List<ExhibitorVO>> getExhibitor(ExhibitorDTO exhibitorDTO) {
        log.info("getExhibitorList - 查询展商列表VO, exhibitorDTO={}", exhibitorDTO);
        return R.successDef(exhibitorService.listExhibitorVOs(exhibitorDTO));
    }

    /**
     * 查询展商VO列表.
     *
     * @param id the id
     * @return the exhibitor
     */
    @ApiOperation("查询展商VO列表")
    @GetMapping("/get/{id}")
    public R<ExhibitorVO> getExhibitor(@PathVariable("id") Long id) {
        log.info("getExhibitor - 获取展商详情, id={}", id);
        try {
            return R.successDef(exhibitorService.getExhibitorVO(id));
        } catch (BizException e) {
            return R.fail(e);
        }
    }

    /**
     * 展商邀请码获取展商信息.
     *
     * @param actorInfoDTO the actor info dto
     * @return the actor info
     */
    @ApiOperation("展商邀请码获取展商信息")
    @PostMapping("/actorInfo/inviteCode")
    public R<List<ActorInfo>> getActorInfo(@RequestBody ActorInfoDTO actorInfoDTO) throws Exception {
        log.info("getActorInfo - 展商邀请码获取展商信息, actorInfoDTO={}", actorInfoDTO);
        return R.successDef(meetActorService.getActorInfoByBuildInviteCode(actorInfoDTO));
    }

    /**
     * 展商邀请码获取展商信息.
     *
     * @param inviteCode   the invite code
     * @param exhibitionId the exhibition id
     * @return the actor info
     * @throws Exception the exception
     */
    @ApiOperation("展商邀请码获取展商信息")
    @GetMapping("/query/inviteCode")
    public R<List<ExhibitorVO>> queryByInviteCode(@RequestParam("inviteCode") String inviteCode,
                                                  @RequestParam("exhibitionId") Long exhibitionId) {
        log.info("queryByInviteCode - 展商邀请码获取展商信息, inviteCode={}, exhibitionId={}", inviteCode, exhibitionId);
        return R.successDef(exhibitorService.listByInviteCode(inviteCode, exhibitionId));
    }

    /**
     * 保存参展商.
     *
     * @param exhibitorDTO the exhibitor dto
     * @return the r
     */
    @ApiOperation("保存参展商")
    @SysLog("绑定展商")
    @PostMapping("/save")
    public R<Boolean> saveExhibitor(@RequestBody ExhibitorDTO exhibitorDTO) {
        log.info("saveExhibitor - 保存参展商, exhibitorDTO={}", exhibitorDTO);
        if (StrUtil.isNotBlank(exhibitorDTO.getInviteCode()) && exhibitorService.checkInviteCodeExist(exhibitorDTO.getInviteCode())) {
            throw BizException.wrap(BuilderExceptionCode.EXHIBITOR_SITE_HAS_BIND.getCode(), "展商邀请码已被使用，请更换邀请码");
        }
        return R.successDef(exhibitorService.saveExhibitor(exhibitorDTO));
    }

    /**
     * 批量保存展商
     *
     * @param list the list
     * @return the r
     */
    @SysLog("绑定展商")
    @PostMapping("/save/batch")
    public R<Boolean> saveBatch(@RequestBody List<ExhibitorDTO> list) {
        log.info("saveBatch - 批量保存展商, list={}", list);
        ExhibitorDTO exhibitorDTO = list.get(0);
        if (StrUtil.isNotBlank(exhibitorDTO.getInviteCode()) && exhibitorService.checkInviteCodeExist(exhibitorDTO.getInviteCode())) {
            throw BizException.wrap(BuilderExceptionCode.EXHIBITOR_SITE_HAS_BIND.getCode(), "展商邀请码已被使用，请更换邀请码");
        }
        return R.successDef(exhibitorService.saveBatch(list));
    }

    /**
     * 保存参展商(仅展商表).
     *
     * @param exhibitorDTO the exhibitor dto
     * @return the r
     */
    @ApiOperation("保存参展商(仅展商表)")
    @SysLog("绑定展商(仅展商表)")
    @PostMapping("/saveExhibitorOnlyExhibitor")
    public R<Boolean> saveExhibitorOnlyExhibitor(@RequestBody List<ExhibitorDTO> exhibitorDTO) {
        log.info("saveExhibitorOnlyExhibitor - 保存参展商(仅展商表), exhibitorDTO={}", exhibitorDTO);
        for (ExhibitorDTO dto : exhibitorDTO) {
            exhibitorService.save(BeanUtil.copyProperties(dto, Exhibitor.class));
        }
        return R.successDef();
    }


    /**
     * 修改参展商.
     *
     * @param exhibitorDTO the exhibitor dto
     * @return the r
     */
    @ApiOperation("修改参展商")
    @SysLog("修改展商")
    @PostMapping("/update")
    public R<Boolean> updateExhibitor(@RequestBody ExhibitorDTO exhibitorDTO) {
        log.info("updateExhibitor - 修改参展商, exhibitorDTO={}", exhibitorDTO);
        try {
            return R.successDef(exhibitorService.updateExhibitor(exhibitorDTO));
        } catch (BizException e) {
            return R.fail(e);
        }
    }

    /**
     * 展位重置.
     *
     * @param id the id
     * @return the r
     */
    @SysLog("展位重置")
    @GetMapping("/reset/{id}")
    public R<Boolean> updateIsReset(@PathVariable("id") Long id) {
        log.info("updateIsReset - 更新展位重置, id={}", id);
        try {
            return R.successDef(exhibitorService.updateIsReset(id));
        } catch (BizException e) {
            return R.fail(e);
        }
    }

    /**
     * 更新展商应付保证金金额.
     *
     * @param exhibitorDTO the exhibitor dto
     * @return the r
     */
    @PostMapping("/update/shouldEarnestMoney")
    public R<Boolean> updateShouldEarnestMoney(@RequestBody ExhibitorDTO exhibitorDTO) {
        log.info("updateShouldEarnestMoney - 更新展商应付金额, exhibitorDTO={}", exhibitorDTO);
        try {
            return R.successDef(exhibitorService.updateShouldEarnestMoney(exhibitorDTO));
        } catch (BizException e) {
            return R.fail(e);
        }
    }

    /**
     * 更新保证金支付状态.
     *
     * @param exhibitorDTO the exhibitor dto
     * @return the r
     */
    @ApiOperation("更新保证金支付状态")
    @PostMapping("/update/earnestMoney/payStatus")
    public R<Boolean> updateEarnestMoneyPayStatus(@RequestBody ExhibitorDTO exhibitorDTO) {
        log.info("updateEarnestMoneyPayStatus - 更新保证金支付状态, exhibitorDTO={}", exhibitorDTO);
        try {
            return R.successDef(exhibitorService.updateEarnestMoneyPayStatus(exhibitorDTO));
        } catch (BizException e) {
            return R.fail(e);
        }
    }

    /**
     * 更新保证金余额.
     *
     * @param exhibitorDTO the exhibitor dto
     * @return the r
     */
    @Deprecated
    @ApiOperation("更新保证金余额")
    @PostMapping("/update/remainEarnestMoney")
    public R<Boolean> updateRemainEarnestMoney(@RequestBody ExhibitorDTO exhibitorDTO) {
        log.info("updateRemainEarnestMoney - 更新保证金余额, exhibitorDTO={}", exhibitorDTO);
        try {
            return R.successDef(exhibitorService.updateRemainEarnestMoney(exhibitorDTO));
        } catch (BizException e) {
            return R.fail(e);
        }
    }

    /**
     * 批量移除展商.
     *
     * @param ids the ids
     * @return the r
     */
    @ApiOperation("批量移除展商")
    @SysLog("解绑展商")
    @PostMapping("/remove")
    public R<Boolean> removeByIds(@RequestBody List<Long> ids) {
        log.info("removeByIds - 批量移除展商, ids={}", ids);
        try {
            return R.successDef(exhibitorService.removeByIds(ids));
        } catch (BizException e) {
            return R.fail(e);
        }
    }
}
